/*================================================================
*   Copyright (C) 2024 baichao All rights reserved.
*
*   文件名称：wait.c
*   创 建 者：baichao
*   创建日期：2024年03月31日
*   描    述：
*
================================================================*/

/*
 * wait（）函数存在一定的局限性：
 *   ·不能等待特定的子进程。如果进程存在多个子进程，而它只想获取某个子进程的退出状态，并不关心其他子进程的退出状态，此时wait（）只能一一等待，通过查看返回值来判断是否为关心的子进程。
 *   ·如果不存在子进程退出，wait（）只能阻塞。有些时候，仅仅是想尝试获取退出子进程的退出状态，如果不存在子进程退出就立刻返回，不需要阻塞等待，类似于trywait的概念。wait（）函数没有提供trywait的接口。
 *   ·wait（）函数只能发现子进程的终止事件，如果子进程因某信号而停止，或者停止的子进程收到SIGCONT信号又恢复执行，这些事件wait（）函数是无法获知的。换言之，wait（）能够探知子进程的死亡，却不能探知子进程的昏迷（暂停），也无法探知子进程从昏迷中苏醒（恢复执行）。
 * 由于上述三个缺点的存在，所以Linux又引入了waitpid（）函数。
 */

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

pid_t r_wait(int *stat_loc) {
  int retval;
  while (((retval = wait(stat_loc)) == -1) && (errno == EINTR)) continue;
  return retval;
}

int main() {
  pid_t childPid;
  int status;

  childPid = fork();
  if (childPid < 0) {
    perror("fork");
    exit(EXIT_FAILURE);
  } else if (childPid == 0) {
    // 子进程逻辑
    printf("Child process\n");
    exit(EXIT_SUCCESS);
  } else {
    // 父进程逻辑
    printf("Parent process\n");

    while ((childPid = r_wait(&status)) != -1) {
      // 处理子进程的退出状态
      printf("Child process completed\n");
    }

    if (errno != ECHILD) {
      perror("r_wait");
      exit(EXIT_FAILURE);
    }
  }

  return 0;
}
